#!/usr/bin/env python3
# coding=utf-8
# Created by han on 2016/5/23

HACFG='haproxy.cfg'
HACFGB='haproxy.cfg.bak'
frist_menu=['获取ha记录','增加ha记录','删除ha记录',]
RAW_FILE='haproxy.cfg'
BAK_FILE='haproxy.cfg.bak'


def return_backend():
    """
    返回现有的backend内容
    :return: 返回backend域名列表
    """
    with open(HACFG,'r',encoding='utf-8') as show_file:         #使用utf-8 打开文件
        count = 0
        show_list=[]
        for show_line in show_file:
            if show_line[:7] == 'backend':
                count+=1
                show_list.append(show_line)
        return show_list


def show_backup(arg):
    """
    细化返回用户选择的backend项，并且让用户选择后返回选择值
    :param arg: 所有的backup组成的列表
    :return: 返回用户选择数字
    """
    for show_list in enumerate(arg):
        print(show_list[0]+1, '.', show_list[1][7:])
    second_chose=input("请输入您的选择：")
    a=user_chose(second_chose)
    if a <= len(arg):
        return a
    else:
        return False


def  view_file(arg1):
    """
    接收用户输入，显示相应backend对应的server信息，功能1的展示函数
    :param arg1:  所有的backend组成的列表
    :param arg1:  用户输入的选项
    :print: 打印backend对应的server内容
    """
    for server_list in enumerate(arg1[0]):
        server_srt = ' '.join(server_list[1])
        print(server_list[0]+1,'.',server_srt,'\n')



def modifiy_file(arg1, arg2, arg3=RAW_FILE, arg4=BAK_FILE):
    """
    接收backend and server 信息写入新的文件
    :param arg1: 接收backend内容 ex: backend:www.baidu.com
    :param arg2: 接收server内容 ex: server 100.1.7.90 100.1.7.90 weight 20 maxconn 3000
    :param arg3: haproxy 原文件
    :param arg4: haproxy 新文件
    :return: 添加的最终功能，添加成功后生成新文件
    """
    with open(arg3,'r',) as har_file,open(arg4,'w',) as haw_file:
        server_content = "        server {0} {1} weigit {2} maxconn {3} \n \n".format(arg2['server'], arg2['server'], arg2['weigit'], arg2['maxconn'])
        backend_content = "%s %s" % (list(arg1)[0],arg1['backend'])
        modi_flag = False
        add_flag = False
        while True:
            ha_line = har_file.readline()
            if ha_line:
                if backend_content.split() == ha_line.split():
                    modi_flag = True
                    add_flag = True
                    haw_file.write(ha_line)
                    continue
                if modi_flag:
                    if ha_line[:7] != "backend" and ha_line[8:14] == "server":
                          haw_file.write(ha_line)
                    else:
                        haw_file.write(server_content)
                        haw_file.write(ha_line)
                        modi_flag = False
                        continue
                else:
                    haw_file.write(ha_line)
            else:
               if add_flag:
                   break
               else:
                    haw_file.write(backend_content)
                    haw_file.write('\n')
                    haw_file.write(server_content)
                    break


def server_list(arg1,arg2,arg3=RAW_FILE):
    """
    取得用户选择的backend内容，展示对应的server节点，并返回对应的server列表
    :param arg1:所有backend的列表。
    :param arg2:选择的backend下标
    :param arg3:原ha文件
    :param arg4:新ha文件
    :return:返回用户要删除的backend和server信息
    """
    if arg2:
        backend_input = [arg1[arg2-1]]
        #print(backend_input,type(backend_input))
        with open(arg3,'r') as hacfgr_file:
            write_flag = False
            server_list=[]
            while True:
                hacfg_line = hacfgr_file.readline()
                if hacfg_line :
                    if backend_input[0] == hacfg_line:
                        write_flag = True
                        continue
                    if write_flag:
                        #print(hacfg_line[8:14])
                        if hacfg_line[8:14] == "server":
                            server_list.append(hacfg_line.split())
                          #  print(server_list)
                        else:
                            write_flag = False
                            return server_list,backend_input
                    else:
                        continue
                else:
                    break
    else:
        print("输入错误请重新输入")

def return_del_server(arg1):
    """
    删除用户选择节点
    :param arg1:[['server', '100.1.7.9', '100.1.7.9', 'weight', '20', 'maxconn', '3000']] server列表
    :return: 返回用户选择的所有server的list
    """

    for server_list in enumerate(arg1):
        server_srt=' '.join(server_list[1])
        print(server_list[0]+1,'.',server_srt)
    del_arg=[]
    bakarg1 = arg1.copy()       #做两个潜拷贝   bakarg1 用来给删除节点使用，
    bakarg2 = arg1.copy()       #bakarg2用来给对照删除的bakarg1生成选择删除列表,原列表给到最后删除比较用。
    while True:
        user_input = input("请选择您要删除的节点,确定后输入【y】确认删除,或者输入【b】退出：")
        if user_input.isdigit() and int(user_input) <= len(bakarg1):
            user_input = int(user_input)
            if  len(bakarg1) > 0:
                bakarg1.pop(user_input-1)                      #server还剩下什么的列表
                del_arg.append(bakarg2[user_input-1])          #server要删除的列表，arg1这个列表应该和bakarg1列表对应上。
                bakarg2.pop(user_input-1)                      #如果这个不减下次循环上面的del还是在原表上减，导致删除的元素对不上
            else:
                print("此节点已经清空")
            for i in enumerate(bakarg1):
                a=' '.join(i[1])
                if a:
                    print(i[0]+1, a)
        elif user_input == "y":
            return del_arg
        elif user_input == "b":
            break
        else:
            print("\n输入有误重新输入")
            break



def input_backend():
    """
    接受用户需要改动或者增加的backend信息：
    :return: 返回 backend 字符串
    """
    backend_input = input("backend: ")
    return {'backend':backend_input}

def add_server():
    """
    要求用户输入需要添加的server信息
    :return: 返回负载节点的完整记录，类型字典。
    """
    server = input("server: ")
    weight = input("weight: ")
    maxconn = input("maxconn: ")
    return {"server":server,"weigit":weight,"maxconn":maxconn}


def user_chose(chose):
    """
    验证用户输入的字符串内容是否是数字，如果是则把字符串转换为数字
    :param arg: 用户输入值
    :return: 将用户输入转换成数字类型返回。
    """
    if chose.isdigit():
        user_input = int(chose)
        return user_input
    else:
        return False


def del_server(arg1,arg2,arg3,arg4 = RAW_FILE, arg5 = BAK_FILE):
    """
    删除选择的sever
    :param arg1: 选择的backend list  ['backend tao.oldboy.org\n']
    :param arg2: 原有的 server和benkend(tulpe)
    :param arg3: 要删除的server [list] [['server', '100.1.7.90', '100.1.7.90', 'weight', '20', 'maxconn', '3000'], ['server', '100.1.7.80', '100.1.7.90', 'weight', '20', 'maxconn', '3000']]
    :return:
    """
    with open(arg4,'r') as rawr_file,open(arg5,'w') as bakw_file:
        rm_flag = True
        ser_flag = False

        while True:
            rawr_list = rawr_file.readline()
            if rawr_list:
                if rm_flag:
                    if arg1[0] == rawr_list:  #如果backend相等
                        ser_flag = True
                        if len(arg2[0]) == len(arg3):        #如果2个server相等
                            rm_flag = False
                            continue            #则不拷贝backend
                        else:
                            bakw_file.write(rawr_list)   #如果判断2个不等就要把backup写上去。
                            continue
                    if ser_flag == True:
                        if rawr_list.split() in arg3:
                            continue
                        if rawr_list.split() == []:
                            ser_flag = False
                    bakw_file.write(rawr_list)
                else:
                    if rawr_list[8:14] != "server":
                        rm_flag = True
                        ser_flag = False
                        bakw_file.write(rawr_list)
            else:
                break



def main():
    """
    主菜单，主函数
    :选择1为展示现有server
    ：选择2为添加server记录
    ：选择3为删除server记录
    """
    while True:
        for frist_list in enumerate(frist_menu):
            print(frist_list[0]+1, '.', frist_list[1])
        chose=input('请输入您的选择： ')
        frist_chose=user_chose(chose)
        if frist_chose <= len(frist_menu):
            if frist_chose == 1:
                back_list = return_backend()                  #back_list=[backend www.oldboy.org,backend buy.oldboy.org]
                domain_num = show_backup(back_list)           #domain_num= 1or 2
                server_list_return = server_list(back_list, domain_num)
                view_file(server_list_return)

            elif frist_chose == 2:
                backend_content = input_backend()
                server_content = add_server()
                modifiy_file(backend_content, server_content)

            elif frist_chose == 3:
                while True:
                    back_list = return_backend()
                    domain_num = show_backup(back_list)
                    del_list=server_list(back_list, domain_num)
                    return_del_list=return_del_server(del_list[0])
                    if return_del_list:                                 #如果return_del_list 不为空则进行下面的删除操作
                        del_server(del_list[1],del_list,return_del_list)
                    else:
                        continue

main()

